<template>
  <div class="editable-param-lists">
    <p class="editable-param-lists-add">
      {{paramItem.label}}
      <el-button v-if="!bIsLimited" @click="onAdd(paramKey)" type="primary" size="small" round>
        添加  <el-icon class="el-icon--right"><Plus /></el-icon>
      </el-button>
    </p>

    <transition-group class="param-lists-flip" name="flip-list" tag="div">
      <template
        :key="childItem.child_item_id ? childItem.child_item_id : childItemIndex"
        v-for="(childItem, childItemIndex) in curParamLists">
          <div class="param-lists-item">

            <p :key="'dropdown_icon_btn_' + childItemIndex"
              class="param-lists-item-title">
                <span style="flex: 1;" @click="handlerDropDown(childItemIndex)"> {{paramItem.label}} {{childItemIndex + 1}} </span>
                <span style="border: 1px solid #f0f0f0; border-radius: 8px; justify-self: flex-start;">
                  <el-tooltip content="Up" placement="top" effect="light">
                    <el-icon size="18" style="margin: 2px 6px;" @click="click2Up(childItemIndex)"><caret-top /></el-icon>
                  </el-tooltip>
                  <el-tooltip content="Down" placement="bottom" effect="light">
                    <el-icon style="margin: 2px 6px;" size="18" @click="click2Down(childItemIndex)"><caret-bottom/></el-icon>
                  </el-tooltip>
                </span>
                <span style="padding: 0 10px; display: flex; min-width: 60px; justify-content: flex-end;" @click="handlerDropDown(childItemIndex)">
                  <el-icon class="param-lists-item-title-arrow" :class="{'is-drop-down': arrShowBox.indexOf(childItemIndex) > -1}"><arrow-up /></el-icon>
                  <i class="param-lists-item-title-arrow-text">
                    {{arrShowBox.indexOf(childItemIndex) > -1 ? '收起' : '展开'}}
                  </i>
                </span>
            </p>

            <transition :key="'drop_down_' + childItemIndex" name="drop-down">
              <div class="param-lists-item-box" v-show="arrShowBox.indexOf(childItemIndex) > -1">
                <template v-for="(childParamItem, childParamKey) in paramItem.param_params">
                  <EditableParam
                    v-if="_isHasOwnProperty(paramVal, childItemIndex)"
                    :key="compId + '_' + parentKeys.join('_') + '_' + paramKey + '_' + ( childItem.child_item_id ? childItem.child_item_id : childItemIndex ) + '_' + childParamKey + '_editable-param-list'"
                    :compId="compId"
                    :paramItem="childParamItem"
                    :paramKey="childParamKey"
                    :paramVal="paramVal[childItemIndex][childParamKey]"
                    :parentKeys="[...parentKeys, paramKey, childItemIndex]"
                    :parentVal="paramVal[childItemIndex]"
                    :original="original"
                    :editableParamsLists="editableParamsLists"
                    :editableParamsLists4Add="editableParamsLists4Add"
                    :type="type"
                    @change="val => onChange(val, childItemIndex)">
                  </EditableParam>
                </template>
              </div>
            </transition>

            <p v-if="!paramItem.del_disable" class="param-lists-item-delete">
              <el-button class="param-lists-item-delete-btn" @click="onDelete(childItemIndex)" type="danger" size="small" plain round>
                删除 <el-icon class="el-icon--right"><close /></el-icon>
              </el-button>
            </p>

          </div>
      </template>
    </transition-group>
  </div>
</template>

<script>
  import { guid } from '@/utils';
  import { _getDeepParamVal, isHasOwnProperty, isArray, isUndefined, isNumber } from '@/utils/public';
  import { defineAsyncComponent } from 'vue';
  export default {
    name: 'editableParamLists',
    data() {
      return {
        arrShowBox: [0],  // 预设 第一个 展开
      }
    },
    props: [
      'modelValue',
      'compId',
      'paramItem',
      'paramKey',
      'paramVal',
      'parentKeys',
      'parentVal',
      'original',
      'editableParamsLists',
      'editableParamsLists4Add',
      'type'
    ],
    emits: ['success'],
    computed: {
      curParamLists() {
        return this.paramVal || [];
      },

      /* 数组添加 limit */
      bIsLimited() {
        const newLen = isArray( this.paramVal ) ? this.paramVal.length : 0;
        const { limit } = this.paramItem;
        if( isNumber( limit ) && limit > 0 && newLen >= limit ) return true;
        return false;
      },

      /* param_effect_parent */
      bIsEffected() {
        return this.paramItem && this.paramItem.param_effect_parent;
      },
      curEffectParentVal() {
        // 1. param_effect_parent 不存在
        if(!this.bIsEffected) return;

        // 2. param_effect_parent 存在；
        //    获取 effect_parent_keys 对应的值
        //    TODO: effect_parent_keys 存在  ？
        //    ‘ARRAY_NUM’ 同于处理 数组数据 的键
        let effect_parent_keys = this.paramItem.param_effect_parent.effect_parent_keys;
        effect_parent_keys = effect_parent_keys.map((key, index) => {
          if(key === 'ARRAY_NUM') return isUndefined(this.parentKeys[index]) ? key : this.parentKeys[index];
          return key;
        })
        if( !isArray( effect_parent_keys ) || effect_parent_keys.length <= 0 ) return;
        const _curEffectParentVal = _getDeepParamVal(this.original, _.cloneDeep(effect_parent_keys));
        if(_curEffectParentVal && _curEffectParentVal.message && _curEffectParentVal.message=='EndIterative') return;

        return _curEffectParentVal;
      },
      bIsEffectListAddItem() {
        // 1. param_effect_parent 不存在
        if(!this.bIsEffected) return false;

        // 2. param_effect_parent 存在；
        const effect_type = this.paramItem.param_effect_parent.effect_type;
        const effect_list_params = this.paramItem.param_effect_parent.effect_list_params;
        if( effect_list_params &&
          isArray(effect_list_params) &&
          effect_type.indexOf( 'ADD_ITEM' ) > -1 ) return true;
        return false;
      },
    },
    components: {
      'EditableParam': defineAsyncComponent(() => import('@/views/card/components/recursion/EditableParam.vue')),
    },
    methods: {
      /* change & update */
      onChange(val, index) {
        let newParamVal = _.cloneDeep(this.paramVal);
        // let newParamVal = this.paramVal;
        newParamVal[index] = val;
        this.$emit('success', newParamVal);
      },
      onAdd(paramKey) {
        // 0. limit
        const newLen = isArray( this.paramVal ) ? this.paramVal.length : 0;
        const { limit } = this.paramItem;
        if( isNumber( limit ) && limit > 0 && newLen >= limit ) {
          this.$message({
            message: '添加个数已达上限！',
            type: 'warning'
          });
          return;
        }

        // 1. 处理 add newChildParamsObj
        let newChildParamsObj;
        if( this.bIsEffectListAddItem ) {
          // 1.1 取 CardEditableParamsDefaultLists4ListAdd > effect_list_params_keys
          const effect_list_params = _.cloneDeep(this.paramItem.param_effect_parent.effect_list_params);
          const new_effect_list_params = effect_list_params.filter((param) => {
            return param.effect_regular.test(this.curEffectParentVal)
          });
          if(new_effect_list_params.length <= 0) newChildParamsObj = null;
          else {
            const effect_list_params_keys = new_effect_list_params[0].effect_list_params_keys;
            newChildParamsObj = _getDeepParamVal(this.editableParamsLists4Add[this.type], effect_list_params_keys);
          }
        }
        else {
          newChildParamsObj = this.editableParamsLists4Add[this.type] &&
            this.editableParamsLists4Add[this.type][paramKey] &&
            _.cloneDeep(this.editableParamsLists4Add[this.type][paramKey][0]);
        }
        if(!newChildParamsObj) return;  // 添加失败

        // 2. update
        newChildParamsObj.child_item_id = this.parentKeys.join("_") + guid();
        const newParamVal = isArray(this.paramVal)
          ? [
            ...this.paramVal,
            newChildParamsObj,
          ]
          : [
            newChildParamsObj
          ];
        this.$emit('success', newParamVal);
      },
      onDelete(childItemIndex) {
        // 1. 处理 delete newChildParamsObj
        // let newParamVal = _.cloneDeep(this.paramVal);
        let newParamVal = this.paramVal;
        newParamVal.splice(childItemIndex, 1);
        this.$emit('success', newParamVal);

        // 2. handlerDropDown
        if(this.arrShowBox.indexOf(childItemIndex) > -1) this.handlerDropDown(childItemIndex);
      },
      click2Up(childItemIndex) {
        if(childItemIndex <= 0) return;  // up失败
        // let newParamVal = _.cloneDeep(this.paramVal);
        let newParamVal = this.paramVal;
        const childItem = newParamVal.splice(childItemIndex, 1)[0];
        newParamVal.splice(childItemIndex - 1, 0, childItem);
        this.$emit('success', newParamVal);
      },
      click2Down(childItemIndex) {
        if(childItemIndex < 0 || childItemIndex + 1 >= this.paramVal.length) return;  // down失败
        // let newParamVal = _.cloneDeep(this.paramVal);
        let newParamVal = this.paramVal;
        const childItem = newParamVal.splice(childItemIndex, 1)[0];
        newParamVal.splice(childItemIndex + 1, 0, childItem);
        this.$emit('success', newParamVal);
      },

      /* dropdown */
      handlerDropDown(index) {
        if(this.arrShowBox.indexOf(index) == -1) this.arrShowBox.push(index);
        else this.arrShowBox.splice(this.arrShowBox.indexOf(index), 1);
      },

      /* 工具类：数据处理 */
      _isHasOwnProperty(obj, key) {
        return isHasOwnProperty(obj, key);
      },
    },
  }
</script>

<style lang="scss">
  @import '@/assets/scss/common.scss';

  .flip-list-move {
    transition: transform .5s;
  }
  .drop-down-enter-active, .drop-down-leave-active {
    opacity: 1;
    transform: scaleY(1);
    transition: transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);
    transform-origin: center top;
  }
  .drop-down-enter, .drop-down-leave-active {
    opacity: 0;
    transform: scaleY(0);
  }

  .editable-param-lists {
    position: relative;
    display: block;
    margin: 5px 10px;
    padding: 16px 6px;
    // width: 200px;
    min-height: 200px;
    border-radius: 2px;
    box-shadow: 0 0 4px 0 rgba(18,123,255,.1);
    background: #fff;

    &:hover {
      background: rgb(254, 240, 240, .2);
    }

    .editable-param-lists-add {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 20px;
      font-size: 14px;
    }

    .param-lists-flip {
      .param-lists-item {
        padding: 10px 0;
        margin: 15px 0;
        border: 1px solid #fff;
        border-radius: 2px;
        background: #fff;
        box-shadow: 0 0 4px 0 rgba(18,123,255,.1);
        transition: all .3s ease;

        &:hover {
          background: #fcfcfc;
          border-color: #b3d8ff;
        }

        .param-lists-item-title {
          display: flex;
          justify-content: flex-end;
          align-items: center;
          padding: 0px 8px 10px 8px;
          line-height: 1;
          color: #aaa;
          font-size: 14px;

          span {
            cursor: pointer;

            i {
              cursor: pointer;

              &::before {
                cursor: pointer;
              }
            }
            i:active {
              color: #127BFF;
            }

            &:hover {
              color: #409eff;
            }
          }

          .param-lists-item-title-arrow {
            transition: transform .3s ease;
          }
          .param-lists-item-title-arrow-text {
            display: none;
            margin-left: 2px;
            font-size: 12px;
            font-style: normal;
            transform-origin: center right;
            animation: openRight .3s ease 1;
          }
          .is-drop-down {
            transform: rotate(180deg);
          }

          &:hover {
            .param-lists-item-title-arrow-text {
              display: inline;
            }
          }
        }

        .param-lists-item-delete {
          display: flex;
          justify-content: flex-end;
          padding: 0 8px;
          margin-top: 10px;

          .param-lists-item-delete-btn {
            padding: 5px 15px !important;
          }
        }
      }
    }
  }
</style>
